﻿using Coolzon.Common;
using Coolzon.UI.Core.Parts;
using CPPEI.Coolzon.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using RT = Coolzon.Metadata.Runtime;

namespace Coolzon.UI.Core
{
    [System.ComponentModel.DisplayName("场景")]
    public partial class Scene : ContentControl, IComponent, IScriptHost//, IPartContainer
    {
        static Scene()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Scene), new FrameworkPropertyMetadata(typeof(Scene)));
        }

        //public static XEvent XEventOnReceiveNetEvent = XEventManager.Register(typeof(Scene),
        //    "OnReceiveNetEvent",
        //    new XEventArgument("sender", typeof(Script.PartScriptObject)),
        //    new XEventArgument("data", typeof(Script.SceneNetScriptObject)));

        private Runtime.Script.SceneScriptObject _scriptObject;

        private List<Area> _areas;

        private Canvas _canvas;
        public RT.Scene SceneMatadata { get; set; }

        public ChildrenPosInfo ChildrenPosInfo { get; set; }

        public Scene()
        {
            _areas = new List<Area>();
            ChildrenPosInfo = new ChildrenPosInfo();
            //_partCollection = new PartCollection(this);
            //Background = new SolidColorBrush(Colors.White);

            _canvas = new Canvas();
            this.Content = _canvas;
        }

        public string Caption { get; set; }

        /// <summary>
        /// 滚动动画对象
        /// </summary>
        Storyboard _loopAnimation;
        DoubleAnimation _loopDoubleAnimation;
        /// <summary>
        /// 动画结束时要到达的目标值，用于动画还没结束又收到新的滚动事件
        /// </summary>
        double _loopAnimationDestValue;

        #region implement IScriptHost
        public object GetScriptObject()
        {
            if(_scriptObject == null)
            {
                _scriptObject = new Runtime.Script.SceneScriptObject(this);
            }
            return _scriptObject;
        }
        #endregion

        #region implement IComponent
        public string XFullName { get; set; }

        public void Init(PartContext context)
        {
            for(int index = 0; index < _areas.Count; index++)
            {
                _areas[index].Init(context);
            }
        }

        public void Active(PartContext context)
        {
            for(int index = 0; index < _areas.Count; index++)
            {
                _areas[index].Active(context);
            }
        }

        public void Deactive()
        {
        }

        public void Destroy()
        {
            for (int index = 0; index < _areas.Count; index++)
            {
                _areas[index].Destroy();
            }
        }
        #endregion

        /// <summary>
        /// 设置元数据
        /// </summary>
        /// <param name="sceneMetadata"></param>
        public void SetMetadata(RT.Scene sceneMetadata)
        {
            this.SceneMatadata = sceneMetadata;
        }

        /// <summary>
        /// 重置区域的位置
        /// </summary>
        public void ResetRootAreaPos()
        {
            //if (SceneMatadata == null)
            //{
            //    Logger.WarningToTag("Coolzon.UI", string.Format("场景:{0}ResetRootAreaPos，SceneMetadata为null", this.Name));
            //    return;
            //}
            //if (SceneMatadata.Areas == null)
            //{
            //    Logger.WarningToTag("Coolzon.UI", string.Format("场景:{0}ResetRootAreaPos，SceneMetaAreas为null", this.Name));
            //    return;
            //}
            //if (SceneMatadata.IsAllowSwapArea)
            //{
            //    double leftOffset = 0;
            //    for (int index = 0; index < SceneMatadata.Areas.Count; index++)
            //    {
            //        RT.Area areaMetadata = SceneMatadata.Areas[index];
            //        Area area = this.GetChildPart(areaMetadata.Name, false) as Area;
            //        if (area != null)
            //        {
            //            area.Left = leftOffset;
            //            leftOffset += area.Width;

            //            ChildrenPosInfo.Set(areaMetadata.Name, area.Left);
            //        }
            //    }
            //}
        }

        public void ResetHorizontalLoop()
        {
            if (_loopAnimation != null)
            {
                _loopDoubleAnimation.From = 0;
                _loopDoubleAnimation.To = 0;
                _loopAnimation.Begin(this);
            }
            _destHLoopOffset = 0;

            HActualLoopOffset = 0;
            HVirtualLoopOffset = this.ActualWidth;
        }

        /// <summary>
        /// 小于0，往左
        /// 大于0，往右
        /// </summary>
        /// <param name="offset"></param>
        public void HorizontalLoop(double offset)
        {
            this.Dispatcher.Invoke(() =>
            {
                _destHLoopOffset += offset;
                if (CurrentHLoopOffset == 0 && _destHLoopOffset == 0)
                {
                    return;
                }

                if (_loopAnimation == null)
                {
                    _loopAnimation = new Storyboard();
                    _loopAnimation.Name = string.Format("LSB{0}", Guid.NewGuid().ToString("N"));

                    Logger.DebugToTag("UI", string.Format("Loop Scene animation from:{0} to:{1}, to1:{2}", CurrentHLoopOffset, _destHLoopOffset, _destHLoopOffset));
                    _loopDoubleAnimation = new DoubleAnimation(CurrentHLoopOffset, _destHLoopOffset, new Duration(TimeSpan.FromMilliseconds(500)));
                    _loopDoubleAnimation.AccelerationRatio = 0.1d;
                    _loopDoubleAnimation.DecelerationRatio = 0.4d;
                    Storyboard.SetTarget(_loopDoubleAnimation, this);
                    Storyboard.SetTargetProperty(_loopDoubleAnimation, new PropertyPath(Scene.CurrentHLoopOffsetProperty));
                    _loopAnimation.Children.Add(_loopDoubleAnimation);
                }
                else
                {
                    _loopDoubleAnimation.From = CurrentHLoopOffset;
                    _loopDoubleAnimation.To = _destHLoopOffset;
                }

                _loopAnimation.Begin(this);
            });
        }

        void _loopAnimation_Completed(object sender, EventArgs e)
        {
            ClockGroup clock = sender as ClockGroup;
            Storyboard sourceStoryboard = clock.Timeline as Storyboard;
            if (sourceStoryboard.Name == _loopAnimation.Name)
            {
                Storyboard temp = _loopAnimation;
                _loopAnimation = null;
                temp.Stop();
                temp.Remove();

                CurrentHLoopOffset = _destHLoopOffset;
                _destHLoopOffset = _destHLoopOffset % this.ActualWidth;
                CurrentHLoopOffset = _destHLoopOffset;
                Logger.DebugToTag("UI", string.Format("Loop Scene animation completed CurrentHLoopOffset:{0} _destHLoopOffset:{1}", CurrentHLoopOffset, _destHLoopOffset));
            }
        }

        private void UpdateLoopRenderState(double currentHLoopOffset)
        {
            double hActualLoopOffset = 0;
            double hVirtualLoopOffset = 0;
            hActualLoopOffset = currentHLoopOffset;
            hVirtualLoopOffset = this.ActualWidth + currentHLoopOffset;
            //Common.Logger.DebugToTag("UI", "Scene HLoop HActualLoopOffset:{0}, HVirtualLoopOffset:{1}, AcutalWidth:{2}",
            //    hActualLoopOffset,
            //    hVirtualLoopOffset,
            //    this.ActualWidth);
            if (hActualLoopOffset > this.ActualWidth)
            {
                hActualLoopOffset = (hActualLoopOffset % this.ActualWidth) - this.ActualWidth;
            }
            else if (hActualLoopOffset < -this.ActualWidth)
            {
                hActualLoopOffset = this.ActualWidth + (hActualLoopOffset % this.ActualWidth);
            }
            else if (hActualLoopOffset == this.ActualWidth)
            {
                hActualLoopOffset = 0;
            }

            if (hVirtualLoopOffset > this.ActualWidth)
            {
                if (hActualLoopOffset > 0)
                {
                    hVirtualLoopOffset = (hVirtualLoopOffset % this.ActualWidth) - this.ActualWidth;
                }
                else
                {
                    hVirtualLoopOffset = (hVirtualLoopOffset % this.ActualWidth);// -this.ActualWidth;
                }
            }
            else if (hVirtualLoopOffset < -this.ActualWidth)
            {
                if (hActualLoopOffset > 0)
                {
                    hVirtualLoopOffset = (hVirtualLoopOffset % this.ActualWidth);
                }
                else
                {
                    hVirtualLoopOffset = this.ActualWidth + (hVirtualLoopOffset % this.ActualWidth);
                }
            }

            //Common.Logger.DebugToTag("UI", "Scene HLoop adjusted HActualLoopOffset:{0}, HVirtualLoopOffset:{1}",
            //    hActualLoopOffset,
            //    hVirtualLoopOffset);
            HActualLoopOffset = hActualLoopOffset;
            HVirtualLoopOffset = hVirtualLoopOffset;
        }

        #region override Part

        //protected override void OnInit(PartContext context)
        //{
        //    for (int index = 0; index < this._partCollection.Count; index++)
        //    {
        //        this._partCollection[index].Create(context);
        //    }

        //    base.OnInit(context);
        //}

        //protected override void OnActive(PartContext context)
        //{
        //    HorizontalLoop(0);

        //    for (int index = 0; index < _partCollection.Count; index++)
        //    {
        //        _partCollection[index].Active(context);
        //    }
        //    base.OnActive(context);
        //}

        //protected override void OnDeactive(PartContext context)
        //{
        //    if (_loopAnimation != null)
        //    {
        //        _loopAnimation.Stop();
        //        _loopAnimation.Remove();
        //        _loopAnimation = null;
        //    }

        //    for (int index = 0; index < _partCollection.Count; index++)
        //    {
        //        _partCollection[index].Deactive();
        //    }

        //    base.OnDeactive(context);
        //}

        //protected override void OnDestroy()
        //{
        //    if (_loopAnimation != null)
        //    {
        //        _loopAnimation.Stop();
        //        _loopAnimation.Remove();
        //        _loopAnimation = null;
        //    }

        //    for (int index = 0; index < _partCollection.Count; index++)
        //    {
        //        _partCollection[index].Destroy();
        //    }

        //    // 移除引用
        //    for (int index = 0; index < _partCollection.Count; index++)
        //    {
        //        _canvas.Children.Remove(_partCollection[index]);

        //        _partCollection[index].ParentPart = null;
        //    }

        //    _partCollection.Clear();

        //    base.OnDestroy();
        //}

        //protected override void OnFrozen()
        //{
        //    for (int index = 0; index < this._partCollection.Count; index++)
        //    {
        //        this._partCollection[index].Frozen();
        //    }
        //    base.OnFrozen();
        //}

        //protected override void OnUnfreeze()
        //{
        //    for (int index = 0; index < this._partCollection.Count; index++)
        //    {
        //        this._partCollection[index].Unfreeze();
        //    }
        //    base.OnUnfreeze();
        //}

        //protected override void OnReset()
        //{
        //    ResetHorizontalLoop();
        //    ResetRootAreaPos();

        //    for (int index = 0; index < this._partCollection.Count; index++)
        //    {
        //        this._partCollection[index].Reset();
        //    }
        //}

        public Point XGetContentPos()
        {
            return new Point(this.Padding.Left, this.Padding.Top);
        }

        #endregion

        /// <summary>
        /// 根据坐标获取根节点的区域对象
        /// </summary>
        /// <param name="ptInScene">场景中的坐标点</param>
        /// <returns></returns>
        public Area GetRootArea(Point ptInScene)
        {
            for (int index = 0; index < this._areas.Count; index++)
            {
                Area areaPart = this._areas[index];
                if (areaPart.Left <= ptInScene.X
                    && areaPart.Top <= ptInScene.Y
                    && areaPart.Left + areaPart.Width >= ptInScene.X
                    && areaPart.Top + areaPart.Height >= ptInScene.Y)
                {
                    return areaPart;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取场景中所有的区域（根级的）
        /// </summary>
        /// <returns></returns>
        public List<Area> GetRootAreas()
        {
            return _areas;
        }

        /// <summary>
        /// 从场景中获取当前区域左侧的区域对象.
        /// <para>如果该区域已经位于最左侧则返回自己.</para>
        /// </summary>
        /// <param name="currentArea">当前区域对象</param>
        /// <returns>当前区域左侧的区域</returns>
        public Area GetLeftRootArea(Area currentArea)
        {
            // 当前区域左侧区域的left值应该小于当前区域的left值，且大于任何left小于当前区域的其他区域
            Area leftArea = null;
            for (int index = 0; index < this._areas.Count; index++)
            {
                Area areaPart = this._areas[index];
                if (areaPart.Left < currentArea.Left)
                {
                    if (leftArea == null)
                    {
                        leftArea = areaPart;
                    }
                    else if (areaPart.Left > leftArea.Left)
                    {
                        leftArea = areaPart;
                    }
                }
            }

            if (leftArea == null)
            {
                leftArea = currentArea;
            }

            return leftArea;
        }

        /// <summary>
        /// 从场景中获取当前区域右侧的区域对象.
        /// <para>如果该区域已经位于最右侧则返回自己.</para>
        /// </summary>
        /// <param name="currentArea">当前区域对象</param>
        /// <returns>当前区域右侧的区域</returns>
        public Area GetRightRootArea(Area currentArea)
        {
            // 当前区域左侧区域的left值应该大于当前区域的left值，且小于任何left大于当前区域的其他区域
            Area rightArea = null;
            for (int index = 0; index < this._areas.Count; index++)
            {
                Area areaPart = this._areas[index];
                if (areaPart.Left > currentArea.Left)
                {
                    if (rightArea == null)
                    {
                        rightArea = areaPart;
                    }
                    else if (areaPart.Left < rightArea.Left)
                    {
                        rightArea = areaPart;
                    }
                }
            }

            if (rightArea == null)
            {
                rightArea = currentArea;
            }

            return rightArea;
        }

        //public override Part GetPartAtPoint(Type type, Point pointInRoot, UIElement rootElement)
        //{
        //    if (Visibility != System.Windows.Visibility.Visible)
        //    {
        //        return null;
        //    }
        //    Part part = null;
        //    // Point absolutePoint = this.TranslatePoint(new Point(0, 0), rootElement);
        //    for (int index = 0; index < this._partCollection.Count; index++)
        //    {
        //        part = this._partCollection[index].GetPartAtPoint(type, pointInRoot, rootElement);
        //        if (part != null)
        //        {
        //            return part;
        //        }
        //    }
        //    return base.GetPartAtPoint(type, pointInRoot, rootElement);
        //}

        ///// <summary>
        ///// 测试是否x，y点是否命中了组件实例
        ///// </summary>
        ///// <param name="pointInScene">场景中的坐标点</param>
        ///// <returns></returns>
        //public override XHitResult XHitTest(Point pointInScene)
        //{
        //    if (Visibility != System.Windows.Visibility.Visible)
        //    {
        //        return new XHitResult(false, null, default(Point));
        //    }

        //    Point pos = this.XGetAbsolutePos();
        //    Size size = this.XGetSize();

        //    if (pointInScene.X >= pos.X
        //        && pointInScene.Y >= pos.Y
        //        && pointInScene.X <= pos.X + size.Width
        //        && pointInScene.Y <= pos.Y + size.Height)
        //    {
        //        for (int index = this._partCollection.Count - 1; index >= 0; index--)
        //        {
        //            XHitResult hitResult = this._partCollection[index].XHitTest(pointInScene);
        //            if (hitResult.IsSuccess)
        //            {
        //                return hitResult;
        //            }
        //        }
        //        return new XHitResult(true, this, new Point(pointInScene.X - pos.X, pointInScene.Y - pos.Y));
        //    }
        //    return new XHitResult(false, null, default(Point));
        //}

        ///// <summary>
        ///// 测试是否x，y点是否命中了组件实例
        ///// </summary>
        ///// <typeparam name="T">命中的组件必须属于这个类型</typeparam>
        ///// <param name="pointInScene">场景中的坐标点</param>
        ///// <returns></returns>
        //public override XHitResult XHitTest<T>(Point pointInScene)
        //{
        //    if (Visibility != System.Windows.Visibility.Visible)
        //    {
        //        return new XHitResult(false, null, default(Point));
        //    }

        //    Type type = typeof(T);
        //    Point pos = this.XGetAbsolutePos();
        //    Size size = this.XGetSize();

        //    if (pointInScene.X >= pos.X
        //        && pointInScene.Y >= pos.Y
        //        && pointInScene.X <= pos.X + size.Width
        //        && pointInScene.Y <= pos.Y + size.Height)
        //    {
        //        for (int index = this._partCollection.Count - 1; index >= 0; index--)
        //        {
        //            XHitResult hitResult = this._partCollection[index].XHitTest<T>(pointInScene);
        //            if (hitResult.IsSuccess)
        //            {
        //                return hitResult;
        //            }
        //        }
        //        if (this.GetType() == type || this.GetType().IsSubclassOf(type)
        //            || type.IsAssignableFrom(this.GetType()))
        //        {
        //            return new XHitResult(true, this, new Point(pointInScene.X - pos.X, pointInScene.Y - pos.Y));
        //        }
        //    }
        //    return new XHitResult(false, null, default(Point));
        //}

        //#region PartContainer


        ///// <summary>
        ///// 添加子组件
        ///// </summary>
        ///// <param name="part"></param>
        ////public void AddPart(Part part)
        ////{
        ////    if (ValidateChildType(part.GetType()))
        ////    {
        ////        if (part is Area)
        ////        {
        ////            this._subAreas.Add((Area)part);
        ////        }
        ////        _partCollection.Add(part);

        ////        _canvas.Children.Add(part);
        ////        Canvas.SetZIndex(part, _canvas.Children.Count - 1);

        ////        Canvas.SetLeft(part, part.Left);
        ////        Canvas.SetTop(part, part.Top);

        ////        part.ParentPart = this;
        ////    }
        ////}

        ////public void XRemovePart(Part part)
        ////{
        ////    if (part is Area)
        ////    {
        ////        this._subAreas.Remove((Area)part);
        ////    }
        ////    _partCollection.Remove(part);

        ////    _canvas.Children.Remove(part);
        ////}

        //public Part GetChildPart(string partName, bool isRecursive)
        //{
        //    return _partCollection.GetChildPart(partName, isRecursive);
        //}

        ///// <summary>
        ///// 根据类型来获取组件里包含的子组件
        ///// </summary>
        ///// <param name="isRecursive"></param>
        ///// <returns></returns>
        //public List<T> GetChildPartByType<T>(bool isRecursive)
        //{
        //    return _partCollection.GetChildPartByType<T>(isRecursive);
        //}

        //public bool ValidateChildType(Type childType)
        //{
        //    if (childType == typeof(Area) || childType.IsSubclassOf(typeof(Area)))
        //    {
        //        return true;
        //    }
        //    else if (childType == typeof(Frame) || childType.IsSubclassOf(typeof(Frame)))
        //    {
        //        return true;
        //    }
        //    return false;
        //}

        ///// <summary>
        ///// 获取实际的可存放组件的容器控件
        ///// </summary>
        ///// <returns></returns>
        //public UIElement GetContentContainer()
        //{
        //    return this._canvas;
        //}

        //public void BringPartTo(Part part, int index)
        //{
        //    //XRemovePart(part);

        //    //if (part is Area)
        //    //{
        //    //    this._subAreas.Add((Area)part);
        //    //}
        //    //_partCollection.Insert(part, index);

        //    //_canvas.Children.Insert(index, part);
        //    //Canvas.SetZIndex(part, index);

        //    //Canvas.SetLeft(part, part.Left);
        //    //Canvas.SetTop(part, part.Top);

        //    //part.ParentPart = this;
        //}

        //public int GetPartIndex(Part part)
        //{
        //    if (part != null)
        //    {
        //        if (_partCollection != null && _partCollection.Count > 0)
        //        {
        //            for (int index = 0; index < _partCollection.Count; index++)
        //            {
        //                if (_partCollection[index] == part)
        //                {
        //                    return index;
        //                }
        //            }
        //        }
        //    }
        //    return -1;
        //}

        //public int GetSendToBackIndex(Part part)
        //{
        //    return 0;
        //}

        //public int GetBringToFrontIndex(Part part)
        //{
        //    return _partCollection.Count - 1;
        //}
        //public int GetForwardIndex(Part part)
        //{
        //    int index = GetPartIndex(part);
        //    return index < _partCollection.Count - 1 ? index + 1 : index;
        //}

        //public int GetBackwardIndex(Part part)
        //{
        //    int index = GetPartIndex(part);
        //    return index > 0 ? index - 1 : index;
        //}

        //public Tuple<Point?, Point?, byte> GetAlignLinePoint(Part part, double left = -1, double top = -1, double right = -1, double bottom = -1)
        //{
        //    //00表示left和top，01表示right和top，10表示left和bottom，11表示right和bottom
        //    byte bDirection = 0;
        //    Point? leftOrRight = null;
        //    Point? topOrBottom = null;
        //    double minOffsetX = double.MaxValue;
        //    double minOffsetY = double.MaxValue;
        //    for (int index = 0; index < _partCollection.Count; index++)
        //    {
        //        Part destPart = _partCollection[index];
        //        if (destPart != part)
        //        {
        //            if (left >= 0)
        //            {
        //                if (Math.Abs(destPart.Left - left) < 2 && Math.Abs(destPart.Left - left) < minOffsetX)
        //                {
        //                    minOffsetX = Math.Abs(destPart.Left - left);
        //                    leftOrRight = new Point(destPart.Left, destPart.Top + destPart.Height / 2);
        //                    bDirection &= 2;
        //                }
        //                else if (Math.Abs(destPart.Left + destPart.Width - left) < 2 && Math.Abs(destPart.Left + destPart.Width - left) < minOffsetX)
        //                {
        //                    minOffsetX = Math.Abs(destPart.Left + destPart.Width - left);
        //                    leftOrRight = new Point(destPart.Left + destPart.Width, destPart.Top + destPart.Height / 2);
        //                    bDirection &= 2;
        //                }
        //            }
        //            if (top >= 0)
        //            {
        //                if (Math.Abs(destPart.Top - top) < 2 && Math.Abs(destPart.Top - top) < minOffsetY)
        //                {
        //                    minOffsetY = Math.Abs(destPart.Top - top);
        //                    topOrBottom = new Point(destPart.Left + destPart.Width / 2, destPart.Top);
        //                    bDirection &= 1;
        //                }
        //                else if (Math.Abs(destPart.Top + destPart.Height - top) < 2 && Math.Abs(destPart.Top + destPart.Height - top) < minOffsetY)
        //                {
        //                    minOffsetY = Math.Abs(destPart.Top + destPart.Height - top);
        //                    topOrBottom = new Point(destPart.Left + destPart.Width / 2, destPart.Top + destPart.Height);
        //                    bDirection &= 1;
        //                }
        //            }
        //            if (right >= 0)
        //            {
        //                if (Math.Abs(destPart.Left - right) < 2 && Math.Abs(destPart.Left - right) < minOffsetX)
        //                {
        //                    minOffsetX = Math.Abs(destPart.Left - right);
        //                    leftOrRight = new Point(destPart.Left, destPart.Top + destPart.Height / 2);
        //                    bDirection |= 1;
        //                }
        //                else if (Math.Abs(destPart.Left + destPart.Width - right) < 2 && Math.Abs(destPart.Left + destPart.Width - right) < minOffsetX)
        //                {
        //                    minOffsetX = Math.Abs(destPart.Left + destPart.Width - right);
        //                    leftOrRight = new Point(destPart.Left + destPart.Width, destPart.Top + destPart.Height / 2);
        //                    bDirection |= 1;
        //                }
        //            }
        //            if (bottom >= 0)
        //            {
        //                if (Math.Abs(destPart.Top - bottom) < 2 && Math.Abs(destPart.Top - bottom) < minOffsetY)
        //                {
        //                    minOffsetY = Math.Abs(destPart.Top - bottom);
        //                    topOrBottom = new Point(destPart.Left + destPart.Width / 2, destPart.Top);
        //                    bDirection |= 2;
        //                }
        //                else if (Math.Abs(destPart.Top + destPart.Height - bottom) < 2 && Math.Abs(destPart.Top + destPart.Height - bottom) < minOffsetY)
        //                {
        //                    minOffsetY = Math.Abs(destPart.Top + destPart.Height - bottom);
        //                    topOrBottom = new Point(destPart.Left + destPart.Width / 2, destPart.Top + destPart.Height);
        //                    bDirection |= 2;
        //                }
        //            }
        //        }
        //    }
        //    return new Tuple<Point?, Point?, byte>(leftOrRight, topOrBottom, bDirection);
        //}
        //#endregion

        #region implement IAreaContainer
        public void AddArea(Area area)
        {
            _areas.Add(area);
            _canvas.Children.Add(area);
        }
        #endregion
    }
}
